import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig
} from "axios"

import { ElMessage } from "element-plus"
import { toCamelCase, toSnakeCase } from "./tools"

// 创建 Axios 实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API || "/api", // 基础接口地址
  timeout: 10000, // 请求超时时间增加到 10 秒
  headers: {
    "Content-Type": "application/json"
  },
  withCredentials: true // 是否携带 cookie
})

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 在请求发送之前做一些处理，比如添加 token
    if (config.data) {
      config.data = toSnakeCase(config.data)
    }
    if (config.params) {
      config.params = toSnakeCase(config.params)
    }
    return config
  },
  (error) => {
    // 处理请求错误
    ElMessage.error("请求错误，请稍后重试！")
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 根据后端返回的状态码处理响应
    const { data } = response
    const camelCaseData = toCamelCase(data)
    if (camelCaseData.code && camelCaseData.code !== 200) {
      ElMessage.error(camelCaseData.message || "请求失败！")
      return Promise.reject(new Error(camelCaseData.message || "Error"))
    }
    return camelCaseData
  },
  (error) => {
    // 处理响应错误
    if (error.code === "ECONNABORTED" && error.message.includes("timeout")) {
      ElMessage.error("请求超时，请检查网络或稍后重试！")
    } else if (error.response) {
      const { status, data } = error.response
      switch (status) {
        case 401:
          ElMessage.error("未授权，请重新登录！")
          // 可以跳转到登录页面
          break
        case 403:
          ElMessage.error("拒绝访问！")
          break
        case 404:
          ElMessage.error("请求地址不存在！")
          break
        case 500:
          ElMessage.error("服务器内部错误！")
          break
        default:
          ElMessage.error(data.message || "请求失败！")
      }
    } else {
      ElMessage.error("网络错误，请稍后重试！")
    }
    return Promise.reject(error)
  }
)

// 封装 POST 请求方法
export const post = <T = unknown>(
  url: string,
  data?: Record<string, unknown>,
  config?: AxiosRequestConfig
): Promise<T> => {
  return service.post(url, data, config)
}

// 封装 GET 请求方法
export const get = <T = unknown>(
  url: string,
  params?: Record<string, unknown>,
  config?: AxiosRequestConfig
): Promise<T> => {
  return service.get(url, { params, ...config })
}

// 封装 PUT 请求方法
export const put = <T = unknown>(
  url: string,
  data?: Record<string, unknown>,
  config?: AxiosRequestConfig
): Promise<T> => {
  return service.put(url, data, config)
}

// 封装 DELETE 请求方法
export const del = <T = unknown>(
  url: string,
  params?: Record<string, unknown>,
  config?: AxiosRequestConfig
): Promise<T> => {
  return service.delete(url, { params, ...config })
}

export default service
